import { Component, AfterViewInit, ElementRef, OnInit, Input, ViewChild, Output, EventEmitter } from '@angular/core';
import { SafeStyle, DomSanitizer } from '@angular/platform-browser';
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';

@Component({
  selector: 'el-slider',
  providers: [{
    provide: NG_VALUE_ACCESSOR,
    useExisting: SliderComponent,
    multi: true
  }],
  templateUrl: './slider.component.html',
})
export class SliderComponent implements OnInit, AfterViewInit, ControlValueAccessor {
  private controlChange: any = function () { };
  private controlTouch: any = function () { };
  private sanitizer: any;
  @ViewChild('runway')
  runwayElement!: ElementRef;
  @Input() size: number = 0;
  @Input() start: number = 0;
  @Input() isDragging: boolean = false;
  @Input() disabled: boolean = false;
  @Input() min: number = 0;
  @Input() max: number = 100;
  @Input('tooltip-class') tooltipClass: string = '';
  @Input('show-tooltip') showTooltip: boolean = true;
  @Input('format-tooltip') formatTooltip!: Function;
  @Input() vertical: boolean = false;
  @Input() height: number = 200;
  @Input() model: number = 0;
  @Output() modelChange: EventEmitter<any> = new EventEmitter();
  constructor(sanitizer: DomSanitizer) {
    this.sanitizer = sanitizer;
  }
  ngAfterViewInit(): void {
    this.resetSize();
  }
  writeValue(value: any): void {
    this.model = value;
  }
  registerOnChange(fn: any): void {
    this.controlChange = fn;
  }
  registerOnTouched(fn: any): void {
    this.controlTouch = fn;
  }
  moveChange(nextValue: any) {
    if(this.disabled) {
      return ;
    }
    
    this.model = nextValue;
    this.modelChange.emit(nextValue);
    this.controlChange(nextValue);
  }

  onSliderClick(event:any) {
    if (this.disabled || this.isDragging)
      return;
    this.resetSize();
    var /** @type {?} */ val = this.vertical ? event.clientY : event.clientX;
   
    var _a = this.runwayElement.nativeElement.getBoundingClientRect(), left = _a.left, bottom = _a.bottom;
    var /** @type {?} */ offset = Math.abs(val - (this.vertical ? bottom : left));
    // update value
    this.model = Math.round((offset / this.size) * (this.max - this.min)) + this.min;
  
    this.moveChange(this.model);
    this.makeBarStyle();
  }

  resetSize() {
    if (!this.runwayElement)
      return;
    this.size = this.runwayElement.nativeElement["client" + (this.vertical ? 'Height' : 'Width')];
  }

  makeBarStyle() {
    var /** @type {?} */ val = (this.model - this.min) * 100 / (this.max - this.min);
    var /** @type {?} */ styles = this.vertical ? "height: " + val + "%; bottom: " + this.start + "%;"
      : "width: " + val + "%; left: " + this.start + "%;";
    return this.sanitizer.bypassSecurityTrustStyle(styles);
  }


  makeRunwayStyle() {
    var /** @type {?} */ styles = this.vertical ? "height: " + this.height + "px;" : '';
    return this.sanitizer.bypassSecurityTrustStyle(styles);
  }

  ngOnInit(): void {
    if (!this.model) {
      this.model = this.min;
    }
  }

}
